import { FormComponentKey } from "@/enums/componentKey"
import { traversalTreeStructure, isArray, isObject } from '@/utils/index'
import dayjs from 'dayjs';
import { propertyFormatByNumber, propertyFormatByPercentage, exc, accMul } from "@/utils/format";

export class FormFormat {
  optionsKeyMap: Record<string, Record<string, string>>
  optionsLabelMap: Record<string, Record<string, string>>
  constructor(
      /** 模块 */
      public fieldTypeMap: Record<string, string>,
      public fieldKeyMap: Record<string, string>,
      public optionsRef: Record<string, string>
  ) {
    this.fieldTypeMap = fieldTypeMap
    this.fieldKeyMap = fieldKeyMap
    const keyMap: Record<string, Record<string, string>> = {},
      labelMap: Record<string, Record<string, string>> = {};
    for (const key in optionsRef) {
      keyMap[key] = {};
      labelMap[key] = {};
      traversalTreeStructure(optionsRef[key], (item) => {
        const childKey = item.value ? item.value : item.id;
        const childLabel = item.label ? item.label : item.name;
        if (childKey) {
          keyMap[key][childKey] = childLabel;
          labelMap[key][childLabel] = childKey;
        }
      });
    }
    // 生成key-value映射表
    this.optionsKeyMap = keyMap;
    this.optionsLabelMap = labelMap;
  }
  updateOptionsKeyMap(optionKey: string, optionInfo) {
    // 更新OptionsMap
    const optionMap: Record<string, string> = {}
    traversalTreeStructure(optionInfo, item => {
      const childKey = item.value ? item.value : item.id
      const childLabel = item.label ? item.label : item.name
      if (childKey) {
        optionMap[childKey] = childLabel
      }
    })
    this.optionsKeyMap[optionKey] = optionMap
  }
  getLabelByValue(componentKey, value) {
    if (!value) {
      // 用于过滤空值
      return void 0
    }
    const label = this.optionsKeyMap[componentKey][value] ?? ''
    return label ? label : value
  }
  getValueByLabel(componentKey, label) {
    if (!label) {
      // 用于过滤空值
      return void 0;
    }
    const value = this.optionsLabelMap[componentKey][label] ?? '';
    return value ? value : label;
  }
  getOption(componentKey: string, value: any) {
    return { value, label: this.getLabelByValue(`${this.fieldKeyMap[componentKey]}_options`, value) }
  }
  setMixedTypeValue(key, value, componentProps, showState = true) {
    // 没有字段信息直接返回
    if (!this.fieldTypeMap || !this.fieldTypeMap[key]) {
      return value;
    }
    // 隐藏返回空
    if (!showState) {
      return null;
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        const { numberFormatType = 'number' } = componentProps;
        if (numberFormatType === 'percent') {
          // 移动端百分比需要除以100
          value = exc(value, 100);
        }

        return value;
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdRadioGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        // Label-Value类型的组件，使用[{label,value}]方式提交
        if (isArray(value)) {
          // 表单重置之后级联选择器的值为[''], 导致存值错误，故放弃使用map方法，改为手动push数组
          const arr = [];
          value.forEach((item) => {
            if (item) {
              arr.push(this.getOption(key, item));
            }
          });
          return arr.length ? arr : null;
        } else {
          const singleValue = this.getOption(key, value);
          return singleValue.value ? [singleValue] : null;
        }
      default:
        return value;
    }
  }
  // 返回格式后的数据
  setFormatMixedTypeValue(key, value, componentProps, showState = true) {
    if (!this.fieldTypeMap || !this.fieldTypeMap[key] || !showState) {
      return '';
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        return this.formatInputNumberValue(value, componentProps);
      default:
        return '';
    }
  }
  formatInputNumberValue(value, componentProps) {
    const {
      numberFormatType = 'number',
      numberCurrencySymbol: currencySymbol = '',
      numberPrecision: accuracy = 0,
      numberThousandthSeparator: thousandthSeparator = false,
    } = componentProps;
    const decimal = '.';
    if (!numberFormatType) {
      return '';
    }
    if (numberFormatType === 'percent') {
      value = exc(value, 100);
      return propertyFormatByPercentage(value, { decimal, accuracy });
    } else {
      return propertyFormatByNumber(value, {
        decimal,
        accuracy,
        currencySymbol,
        thousandthSeparator,
      });
    }
  }
  // 获取数据联动中的混合类型数据的label值
  getMixedTypeLabelValue(key, value, componentProps) {
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        const { numberFormatType, numberThousandthSeparator } = componentProps;
        if (numberFormatType === 'percent') {
          // 百分比转原始值
          value = exc(value, 100);
        } else if (numberFormatType === 'number') {
          // 千分位转原始值
          if (numberThousandthSeparator) {
            value = String(value).replace(/$s?|(,*)/g, '');
          }
        }
        return Number(value);
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdRadioGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        // Label-Value类型的组件，使用[{label,value}]方式提交
        if (isArray(value)) {
          switch (value.length) {
            case 0:
              return '';
            case 1:
              const singleValue = this.getLabelByValue(
                  `${this.fieldKeyMap[key]}_options`,
                  value[0],
              );
              return singleValue ?? '';
            default:
              const arr = [];
              value.forEach((item) => {
                let optionLabel;
                if (item) {
                  optionLabel = this.getLabelByValue(`${this.fieldKeyMap[key]}_options`, item);
                  optionLabel && arr.push(optionLabel);
                }
              });
              return arr;
          }
        } else {
          const singleValue = this.getLabelByValue(`${this.fieldKeyMap[key]}_options`, value);
          return singleValue ?? '';
        }
      default:
        return value;
    }
  }
  // 根据组件自身格式化配置项处理回显
  getSelfFormatValue(key, value, componentProps) {
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        const { numberFormatType = 'number' } = componentProps;
        if (value && numberFormatType === 'percent') {
          // 移动端百分比需要除以100
          value = accMul(value, 100);
        }

        return value;
      case FormComponentKey.AntdDatePickerFormPc:
        if (!value) {
          return '';
        }
        return dayjs(value);
      case FormComponentKey.AntdRangePickerFormPc:
        if (!value && !value.length) {
          return [];
        }
        const [start, end] = value;
        return end ? [dayjs(start), dayjs(end)] : [dayjs(start), dayjs(start)];
      default:
        return value;
    }
  }
  // 获取数据联动中的不同组件对应的值
  getMixedTypeLinkageValue(key, value, isSingle, format) {
    if (!value) {
      return this.setDefaultValue(value, key);
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdDatePickerFormPc:
        return dayjs(value).format(format);
      case FormComponentKey.AntdRangePickerFormPc:
        const [start, end] = value;
        return [dayjs(start).format(format), dayjs(end).format(format)];
      case FormComponentKey.AntdInputNumberFormPc:
        // 数字暂时返回原始值，后续处理格式。
        return value;
      case FormComponentKey.AntdRadioGroupFormPc:
        return this.getValueByLabel(`${this.fieldKeyMap[key]}_options`, value[0].label);
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
        return value.map((item) =>
          this.getValueByLabel(`${this.fieldKeyMap[key]}_options`, item.label),
        );
      case FormComponentKey.AlUploadFormPc:
      case FormComponentKey.AlImageUploadFormPc:
        return value;
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        if (!Array.isArray(value)) {
          return value;
        }
        if (isSingle) {
          return value[0].value ?? value[0].id;
        }
        // Label-Value类型的组件，使用[{label,value}]方式提交
        return value.map((item) => item.value ?? item.id);
      default:
        if (isSingle && Array.isArray(value)) {
          return value[0].label;
        }
        return value;
    }
  }
  // 过滤子表单字段
  filterSubformField(dataList) {
    return (
      dataList &&
      dataList.map((item) => {
        Object.keys(item).forEach((field) => {
          if (field !== 'id' && !this.fieldKeyMap.hasOwnProperty(field)) {
            delete item[field];
          }
        });
        return item;
      })
    );
  }
  // 处理选项值类型组件的回显值问题
  getMixedTypeValue(data, key) {
    if (isObject(data) && data.hasOwnProperty('dataList')) {
      return this.filterSubformField(data.dataList);
    }
    if (!data) {
      return this.setDefaultValue(data, key);
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        return data;
      case FormComponentKey.AntdRadioGroupFormPc:
        return data[0].value;
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
        return data.map((item) => item.value);
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        return data.map((item) => item.value ?? item.id);
      default:
        return data;
    }
  }
  // 设置组件初始值
  setDefaultValue(data, key) {
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AlUploadFormPc:
      case FormComponentKey.AlImageUploadFormPc:
        return [];
      default:
        return data;
    }
  }
}
